<?php

/*******************************************************************************
 * 
 * query.class.php
 * 
 * Encapsulation Class for MySQL queries
 * 
 * 
 * @author Stanislas PERRIN <stanislas.perrin@gmail.com> <stan@extramuros.com>
 * 
 ******************************************************************************/

class query extends db
{
	############################################################################
	#
	# PROPRIETES
	#
	############################################################################

	// Timer de démarrage
	protected $startTimer = 0;
	
	// Tableau associatif statique hash_requete => age_requete
	protected static $queriesAges = array();
	
	// IP dont est originaire la requête
	protected $ip = '0.0.0.0';
	
	// Hostname correspondant à l'IP
	protected $hostname = '';
	
	// Domaine extrait du hostname
	protected $domain = '';
	
	// Stats sur la dernière requête
	protected $lastQueryAge = 0; // age de la dernière requête
	protected $lastQuerySize = 0; // taille de la requête SQL
	protected $lastQueryHash = ''; // hash MD5 de la dernière requête
	protected $lastQueryResultSize = 0; // taille du dernier résultat
	protected $lastQueryExecTime = 0; // durée de la dernière requête
	
	// Tableau associatif statique qui stocke les stats par IP
	// $usage[IP]['totalQueryCount'] = n
	// $usage[IP]['totalQueryExecTime'] = t
	// $usage[IP]['totalQueryResultSize'] = b
	// $usage[IP]['averageQueryExecTime'] = t/n // durée moyenne d'execution d'une requête
	// $usage[IP]['averageqQeryResultSize'] = b/n // taille moyenne des résultats de requêtes
	protected static $stats = array();
	
	/**
	 * Tableau des quotas. La structure est la même que pour $stats : pour
	 * chaque mesure, on peut attribuer un seuil qui déterminera
	 */
	protected $quotas = array();
	
	
	/**
	 * Tableau des pauses. La structure est la même que pour $stats : pour
	 * chaque mesure, on peut attribuer une durée de pause avant d'autoriser
	 * une nouvelle requête.
	 * 
	 * La durée de la pause s'exprime en millisecondes
	 */
	protected static $pauses = array();
	
	// Tableau associatif des restrictions sur les requêtes autorisées
	protected $queryRestrictions = array('SELECT','SHOW');
	
	// 
	
	############################################################################
	#
	# CONSTRUCTEUR
	#
	############################################################################
	
	public function __construct($dbConnectionObject=false,$ip=false)
	{
		$this->startTimer = $this->getMicroTime();
		
		if ($dbConnectionObject)
		{
			if ($ip)
			{
				$this->ip = trim($ip);
				$this->hostname = gethostbyaddr($this->ip);
				return parent::__construct($dbConnectionObject);
			}
			throw new debug('Invalid IP address.',-777);
		}
		throw new debug('No or bad connection object !',-777);
	}

	############################################################################
	#
	# DESTRUCTEUR
	#
	############################################################################
	
	public function __destruct()
	{
		// 
	}

	############################################################################
	#
	# METHODES PUBLIQUES
	#
	############################################################################

	/**
	 * 
	 * query()
	 * 
	 */
	public function q($queryString=false)
	{
		// Requête
		$this->queryString = $queryString;
		// Hash MD5 de la req
		$this->queryHash = md5(trim(strtolower($this->queryString)));
		// Taille de la req
		$this->lastQuerySize = strlen($this->queryString);
		// Comptage de la reqête pour
		$this->addNewQuery($ip);
		// Requêtage
		$resultRessource = parent::query($queryString);
		// Age de la req
		$this->lastQueryAge = $this->getMicroTime() - $this->startTimer;
		// Stockage du temps d'execution de la req
		$this->updateQueryAges($this->queryHash,$this->queryExecTime);
		$this->addQueryTime($this->queryExecTime);
		$this->setAllAverageQueryTime($ip);
		return $resultRessource;
	}


	############################################################################
	#
	# METHODES PROTÉGÉES
	#
	############################################################################


	############################################################################
	#
	# METHODES PRIVÉES
	#
	############################################################################

	/**
	 * 
	 * setIP()
	 * 
	 */
	private function setIP($ip=false)
	{
		if ($ip)
		{
			return $this->usage[$ip];
		}
		throw new debug('Invalid IP address.',-777);
	}
	
	/**
	 * 
	 * updateQueryStats()
	 * 
	 */
	private function updateQueryStats()
	{
		
	}
	 
	/**
	 *  
	 * addNewQuery()
	 * 
	 * Ajoute une nouvelle requête au compteur de $ip
	 * 
	 * @param
	 * @return
	 */
	private function addNewQuery()
	{
		if ($this->ip)
		{
			return $this->usages[$this->ip]['totalQueryCount']++;
		}
		throw new debug('IP address unset !',-777);
	}

	/**
	 *  
	 * addQueryTime()
	 * 
	 * Ajoute une nouvelle requête au compteur de $ip
	 * 
	 * @param $ip
	 * @param $duration
	 * @return
	 * 
	 */
	private function addQueryTime()
	{
		if ($ip)
		{
			if ($duration)
			{
				if (is_float($duration))
				{
					$this->usage[$ip]['totalquerytime']+=$this->lastQueryExecTime;
					$this->setAverageQueryTime($ip);
					return $this->usage[$ip]['totalquerytime'];
				}
				throw new debug("$duration is not a float",-777);
			}
			throw new debug('Empty or bad duration',-777);
		}
		throw new debug('Invalid IP address.',-777);
	}


	/**
	 * 
	 * setAverageQueryTime()
	 * 
	 */
	 private function setAverageQueryTime($ip=false)
	 {
		 if ($ip)
		 {
			 $this->usage[$ip]['averagequerytime'] = $this->usage[$ip]['totalquerytime'] / $this->usage[$ip]['totalquerycount'];
		 }
		throw new debug('Invalid IP address.',-777);
	 }

	/**
	 * 
	 * setAllAverageQueryTime()
	 * 
	 * 
	 */
	 private function setAllAverageQueryTime()
	 {
		 foreach($this->usage as $ip => $counters)
		 {
			 $this->setAllAverageQueryTime($ip);
		 }
	 }

}
 
 
?>
